package socketinterface;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;

public class NonBlokingServer {
	private ServerSocketChannel serverChannel;
    private Selector selector;

    public NonBlokingServer(int port) throws ClosedChannelException, SocketException, IOException {
    	
    	// Create SocketChannel
    	serverChannel = ServerSocketChannel.open();
    	serverChannel.socket().setReuseAddress(true);
    	serverChannel.socket().bind(new InetSocketAddress(port));
    	
    	// Set Non Blocking Mode
    	serverChannel.configureBlocking(false);
    	
    	// Generate Selector
    	selector = Selector.open();
    	
    	// Register socketChannel to Selector
    	serverChannel.register(selector, SelectionKey.OP_ACCEPT, new AcceptHandler());
    }
    
    public void start() {
    	try {
    		//Observing by Selector
    		while(selector.select() > 0) {
    			// Take SelectionKey
    			Set<SelectionKey> keys = selector.selectedKeys();
    			for (Iterator<SelectionKey> it = keys.iterator(); it.hasNext();) {
    				SelectionKey key = it.next();
    				it.remove();
    				
    				// Delegate processing to the attached object
    				Handler handler = (Handler)key.attachment();
    				handler.handle(key);
    			}
    		}
    	} catch (ClosedChannelException ex) {
    		System.err.println("Close socket"  + ex.getMessage());
    	} catch (IOException ex) {
    		System.err.println("Communication Err :" + ex.getMessage());
    	} finally {
    		try {
    			for (SelectionKey key: selector.keys()) {
    				key.channel().close();
    			}
    		} catch (IOException ex) {
    			ex.printStackTrace();
    		}
    	}
    }
    
   
    
    
}
